import logging

from flask import flash
from flask_login import current_user

from ..services.svc_containers import link_container_and_user
from ..services.svc_dev_envs import generate_container_name
from ..utils.docker_operator_client import DockerOperatorClient
from ..models import (
    Snapshot,
    HostMachineInfo,
    UserContainerLink,
    ContainerInfoDict,
    DevEnvironment,
)
from ..baseapp import db
from ..configs import get_config
from datetime import datetime

logger = logging.getLogger(__name__)


def get_image_repo_basename(
    container: ContainerInfoDict, snapshot_image_repo: str
) -> str:
    """
    从容器信息中获取镜像仓库的基础名称。
    如果旧容器不是以snapshot_image_repo开头，则镜像名称为源容器的名称
    旧镜像名称需要取最右边的一项。比如 nginx-repo/nginx:1.24.0，则结果应为nginx
    否则直接使用原始容器名称的连接杠的左侧内容
    """
    image_name = container["image"]
    if image_name.startswith(snapshot_image_repo):
        return image_name.split(":")[1].split("--")[0]
    else:
        return container["name"]


def create_snapshot(container_name, snapshot_name, host_machine: HostMachineInfo):
    """
    创建快照：停止容器，创建快照镜像，启动新容器。
    """
    try:
        # 使用 DockerOperatorClient 调用 API
        docker_op_cli = DockerOperatorClient(host_machine.address)

        # 获取旧容器的信息
        container_info = docker_op_cli.get_container_info(container_name)
        logger.info(f"Got container info: {container_info}")

        # 获取容器所属的开发环境
        link = UserContainerLink.query.filter_by(
            container_id=container_info["id"]
        ).first()
        if not link:
            raise ValueError(
                f"UserContainerLink not found for container {container_info['id']}"
            )
        dev_env: DevEnvironment = DevEnvironment.query.get(link.dev_env_id)
        if not dev_env:
            raise ValueError(f"DevEnvironment not found for id {link.dev_env_id}")

        # 停止容器
        docker_op_cli.stop_container(container_name)
        logger.info(f"Stopped container: {container_name}")

        # 创建快照镜像
        ## 获取快照的镜像仓库名称
        snapshot_image_repo = get_config()["snapshot_configs"]["snapshot_repo"]
        if not snapshot_image_repo:
            snapshot_image_repo = "baco3-snapshots"

        # 构建快照镜像的名称
        image_name = f"{snapshot_image_repo}:{dev_env.name}--{snapshot_name}"

        # 将容器导出为镜像
        msg, success = docker_op_cli.export_container_to_image(
            container_name, image_name
        )
        if not success:
            raise Exception(f"Failed to export container to image: {msg}")

        # 启动新容器
        new_container_name = generate_container_name(dev_env.name)
        new_container_info = docker_op_cli.create_container(
            image=image_name,
            name=new_container_name,
            command=dev_env.configs["command"],  # TODO: 这里应该允许自定义覆盖命令
            environment=dev_env.configs["environment"],
            ports=dev_env.configs["ports"],
        )

        # 获取数据库中的旧容器
        old_container_link: UserContainerLink = UserContainerLink.query.filter_by(
            container_id=container_info["id"]
        ).first()

        # 创建新容器的
        new_container_link = UserContainerLink(
            container_id=new_container_info["id"],
            user_id=current_user.id,
            dev_env_id=dev_env.id,
            port=old_container_link.port,
            host_machine_id=host_machine.id,
        )

        # 记录快照信息到数据库
        snapshot = Snapshot(
            dev_env_name=dev_env.name,
            base_image=container_info["image"],
            snapshot_image=image_name,
        )
        db.session.add(new_container_link)
        db.session.add(snapshot)
        db.session.commit()

        return {
            "status": "success",
            "message": f"Snapshot created successfully: {image_name}",
            "new_container_id": new_container_info["id"],
        }
    except Exception as e:
        import traceback

        traceback.print_exc()

        return {"status": "error", "message": str(e)}


def get_snapshots(dev_env_name: str) -> list[Snapshot]:
    """
    根据开发环境的名称，获取该开发环境的所有快照镜像。
    """
    snapshots = Snapshot.query.filter_by(dev_env_name=dev_env_name).all()
    return snapshots


def list_snapshots():
    """
    查看快照：列出所有快照镜像。
    """
    snapshots = Snapshot.query.all()
    return [
        {
            "id": snapshot.id,
            "base_image": snapshot.base_image,
            "snapshot_image": snapshot.snapshot_image,
            "created_at": snapshot.created_at.strftime("%Y-%m-%d %H:%M:%S"),
        }
        for snapshot in snapshots
    ]


def delete_snapshot(snapshot_id):
    """
    删除快照：删除指定的快照镜像。
    """
    try:
        snapshot = Snapshot.query.get(snapshot_id)
        if not snapshot:
            return {"status": "error", "message": "Snapshot not found"}

        # 删除镜像
        client.images.remove(image=snapshot.snapshot_image, force=True)

        # 删除数据库记录
        db.session.delete(snapshot)
        db.session.commit()

        return {
            "status": "success",
            "message": f"Snapshot deleted successfully: {snapshot.snapshot_image}",
        }
    except Exception as e:
        return {"status": "error", "message": str(e)}


def run_snapshot(snapshot_image, container_name):
    """
    运行快照：从快照创建新的容器。
    """
    try:
        # 创建新容器
        container = client.containers.run(
            snapshot_image, detach=True, name=container_name
        )

        return {
            "status": "success",
            "message": f"Container created from snapshot: {container_name}",
            "container_id": container.id,
        }
    except Exception as e:
        return {"status": "error", "message": str(e)}


def create_image_from_snapshot(snapshot_image, new_image_name):
    """
    基于快照创建新镜像。
    """
    try:
        # 获取快照镜像
        image = client.images.get(snapshot_image)

        # 创建新镜像
        client.images.tag(image.id, new_image_name)

        return {"status": "success", "message": f"New image created: {new_image_name}"}
    except Exception as e:
        return {"status": "error", "message": str(e)}
